﻿using MultiLang;
using System;
using System.Collections.Generic;
using System.Linq;

using JetBrains.Annotations;

using Rsdn.SmartApp;

namespace Rsdn.Janus
{
    [Service(typeof(ICommandService))]
    public class CommandService : ICommandService
    {
        private readonly Dictionary<string, ICommandInfo> _commands =
            new Dictionary<string, ICommandInfo>(StringComparer.OrdinalIgnoreCase);

        /// <exception cref="ApplicationException"><c>ApplicationException</c>.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="serviceProvider" /> is <c>null</c>.</exception>
        public CommandService([NotNull] IServiceProvider serviceProvider)
        {
            if (serviceProvider == null)
            {
                throw new ArgumentNullException("serviceProvider");   //MLHIDE
            }

            ExtensionsCache<CommandProviderInfo, ICommandProvider> extensionsCache =
                new ExtensionsCache<CommandProviderInfo, ICommandProvider>(serviceProvider);

            ICommandProvider[] commandProviders = extensionsCache.GetAllExtensions();

            IEnumerable<ICommandInfo> commandInfos = commandProviders.SelectMany(commandProvider => commandProvider.CreateCommands());

            foreach (var commandInfo in commandInfos)
            {
                if (_commands.ContainsKey(commandInfo.Name))
                {
                    throw new ApplicationException(
                        ml.ml_string(11, "Команда '{0}' определена более одного раза.").FormatStr(commandInfo.Name));
                }
                _commands.Add(commandInfo.Name, commandInfo);
            }
        }

        #region ICommandService Members

        public ICollection<ICommandInfo> Commands
        {
            get { return _commands.Values; }
        }

        /// <exception cref="ArgumentNullException"><paramref name="commandName" /> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException">commandName</exception>
        public ICommandInfo GetCommandInfo([NotNull] string commandName)
        {
            if (commandName == null)
            {
                throw new ArgumentNullException("commandName");       //MLHIDE
            }

            ICommandInfo result;
            if (!_commands.TryGetValue(commandName, out result))
            {
                throw new ArgumentException(ml.ml_string(12, "Команда '{0}' не найдена.").FormatStr(commandName), "commandName"); //MLHIDE
            }

            return result;
        }

        /// <exception cref="ArgumentNullException"><paramref name="commandName" /> is <c>null</c>.</exception>
        public bool IsCommandExists([NotNull] string commandName)
        {
            if (commandName == null)
            {
                throw new ArgumentNullException("commandName");       //MLHIDE
            }

            return _commands.ContainsKey(commandName);
        }

        #endregion
    }
}